package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.builder.dto.ExhibitorDTO;
import com.eastfair.builder.enumeration.ExhibitorSiteTypeEnum;
import com.eastfair.builder.vo.ExhibitorVO;
import com.eastfair.builder.vo.ReportBuilderVO;
import com.eastfair.common.dto.AttachmentFileDTO;
import com.eastfair.common.vo.AttachmentFileVO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.venueservice.dao.ArrangementManageMapper;
import com.eastfair.venueservice.dto.ArrangementManageDTO;
import com.eastfair.venueservice.dto.ExhibitionManageQuery;
import com.eastfair.venueservice.entity.ArrangementManage;
import com.eastfair.venueservice.entity.ExhibitionManage;
import com.eastfair.venueservice.entity.ServiceProvider;
import com.eastfair.venueservice.entity.ViolationRecord;
import com.eastfair.venueservice.enumeration.ArrangementManageArrangementSourceEnum;
import com.eastfair.venueservice.enumeration.ArrangementManagePunishStatusEnum;
import com.eastfair.venueservice.enumeration.ServiceProviderTypeEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ArrangementManageVO;
import com.eastfair.venueservice.vo.ExhibitionManageVO;
import com.eastfair.venueservice.vo.ServiceProviderSpaceVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 布撤展现场管理
 * </p>
 *
 * @author lyw
 * @date 2022-08-11
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ArrangementManageServiceImpl extends SuperServiceImpl<ArrangementManageMapper, ArrangementManage> implements ArrangementManageService {

    /**
     * 布撤展管理记录附件类型
     */
    private static final String ARRANGE_MANAGE_BUSINESS_TYPE = "arrangement_manage";

    @Resource
    private ExhibitionManageService exhibitionManageService;

    @Resource
    private ViolationRecordService violationRecordService;

    @Resource
    private ServiceProviderService serviceProviderService;

    @Resource
    private ServiceProviderSpaceService serviceProviderSpaceService;

    @Resource
    private VenueManageAttachFileService venueManageAttachFileService;

    @Resource
    private VenueManageExhibitorService venueManageExhibitorService;

    @Resource
    private VenueManageReportBuilderService venueManageReportBuilderService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ArrangementManage> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(ArrangementManage model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        if (model.getPunishStatus() == null) {
            model.setPunishStatus(ArrangementManagePunishStatusEnum.NOT_PUNISH);
        }
        return R.successDef();
    }

    @Override
    public ExhibitionManageVO queryExhibitionManageByProvider(ExhibitionManageQuery exhibitionManageQuery) {
        log.info("queryExhibitionManageByProvider - 通过服务商查询进行中的展会, exhibitionManageQuery={}", exhibitionManageQuery);
        R<ExhibitionManageVO> result = exhibitionManageService.queryExhibitionManageByProvider(exhibitionManageQuery);
        return result.getData();
    }

    @Override
    public Page<ArrangementManageVO> queryForHome(PageParams<ArrangementManageDTO> params) {
        log.info("queryForHome - 主场查询布撤展管理记录, params={}", params);
        ArrangementManageDTO model = params.getModel();
        model.setIsHomeQuery(true);
        List<String> spaceCodeList = serviceProviderSpaceService.querySpaceCodeListByExhibitionId(model.getExhibitionManageId(), model.getSupervisorId());
        model.setSpaceCodeList(spaceCodeList);
        return queryArrangementManageList(params);
    }

    @Override
    public Page<ArrangementManageVO> queryForHomeCheck(PageParams<ArrangementManageDTO> params) {
        log.info("queryForHomeCheck - 主场巡检查询布撤展管理记录, params={}", params);
        return queryArrangementManageList(params);
    }

    @Override
    public Page<ArrangementManageVO> queryArrangementManageList(PageParams<ArrangementManageDTO> params) {
        log.info("ArrangementManageServiceImpl - 查询布撤展管理列表分页 params={}", params);
        // 查询布撤展管理记录列表
        Page<ArrangementManage> paramPage = params.buildPage();
        ArrangementManageDTO model = params.getModel();
        QueryWrapper<ArrangementManage> queryWrapper = createArrangementManageQueryWrapper(model);
        Page<ArrangementManage> page = page(paramPage, queryWrapper);
        Page<ArrangementManageVO> voPage = ConvertUtil.convertPage(page, ArrangementManageVO.class);
        // 查询布撤展管理附件
        List<ArrangementManageVO> voList = voPage.getRecords();
        if (voList == null || voList.isEmpty()) {
            return voPage;
        }
        List<Long> ids = voList
                .stream()
                .map(ArrangementManageVO::getId)
                .collect(Collectors.toList());
        Map<Long, List<AttachmentFileVO>> fileMap = venueManageAttachFileService.queryMapByBusinessIds(ids, ARRANGE_MANAGE_BUSINESS_TYPE);
        voList.forEach((arrangementManageVO) -> {
            List<AttachmentFileVO> attachmentFileList = fileMap.get(arrangementManageVO.getId());
            arrangementManageVO.setAttachmentFileVOList(attachmentFileList);
        });
        return voPage;
    }

    @Override
    public ArrangementManageVO getArrangementManage(ArrangementManageDTO arrangementManageDTO) {
        log.info("getArrangementManage - 获取布撤展管理详情 params={}", arrangementManageDTO);
        QueryWrapper<ArrangementManage> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ArrangementManage::getId, arrangementManageDTO.getId())
                .eq(Objects.nonNull(arrangementManageDTO.getSupervisorId()),
                        ArrangementManage::getSupervisorId, arrangementManageDTO.getSupervisorId())
                .eq(Objects.nonNull(arrangementManageDTO.getExhibitionManageId()),
                        ArrangementManage::getExhibitionManageId, arrangementManageDTO.getExhibitionManageId())
                .eq(Objects.nonNull(arrangementManageDTO.getSupervisedId()),
                        ArrangementManage::getSupervisedId, arrangementManageDTO.getSupervisedId())
                .eq(ArrangementManage::getIsDeleted, BusinessConstant.DELETE_NO)
                .last("limit 1")
        ;
        ArrangementManage arrangementManage = this.getOne(queryWrapper);
        if (arrangementManage == null) {
            return null;
        }
        ArrangementManageVO arrangementManageVO = BeanUtil.toBean(arrangementManage, ArrangementManageVO.class);
        // 查询服务商的法人与统一社会信用代码
        if (arrangementManage.getSupervisedId() != null) {
            ServiceProvider serviceProvider = serviceProviderService.getById(arrangementManage.getSupervisedId());
            arrangementManageVO.setSupervisedUscc(serviceProvider.getUscc());
            arrangementManageVO.setSupervisedLegalName(serviceProvider.getLegalName());
        }
        // 查询展会名称
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(arrangementManageVO.getExhibitionManageId());
        if (exhibitionManage != null) {
            arrangementManageVO.setExhibitionManageName(exhibitionManage.getExhibitionName());
        }
        // 查询布撤展管理附件
        List<AttachmentFileVO> attachmentFileList = venueManageAttachFileService.queryByBusinessId(arrangementManageVO.getId(), ARRANGE_MANAGE_BUSINESS_TYPE);
        arrangementManageVO.setAttachmentFileVOList(attachmentFileList);
        return arrangementManageVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitForHomeCheck(ArrangementManageDTO arrangementManageDTO) {
        log.info("submitForHome - 主场巡检提交布撤展管理信息, arrangementManageDTO={}", arrangementManageDTO);
        arrangementManageDTO.setArrangementSource(ArrangementManageArrangementSourceEnum.HOME_CHECK);
        if (arrangementManageDTO.getIsCertificate() == null || !arrangementManageDTO.getIsCertificate()) {
            // 不是保存证件的管理记录，直接保存
            saveArrangementManage(arrangementManageDTO);
        } else {
            // 保存证件的管理记录
            saveForHomeCheckCertificate(arrangementManageDTO);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ArrangementManage submitForVenue(ArrangementManageDTO arrangementManageDTO) {
        log.info("submitForVenue - 场馆巡检提交布撤展管理记录, arrangementManageDTO={}", arrangementManageDTO);
        arrangementManageDTO.setArrangementSource(ArrangementManageArrangementSourceEnum.VENUE_CHECK);
        if (arrangementManageDTO.getIsCertificate() == null || !arrangementManageDTO.getIsCertificate()) {
            // 不是保存证件的管理记录，直接保存
            return saveArrangementManage(arrangementManageDTO);
        } else {
            // 保存证件的管理记录
            return saveFoVenueCheckCertificate(arrangementManageDTO);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ArrangementManage saveArrangementManage(ArrangementManageDTO arrangementManageDTO) {
        log.info("saveArrangementManage - 保存布撤展管理信息记录, arrangementManageDTO={}", arrangementManageDTO);
        // 查询展位报馆时的搭建商基本信息
        if (arrangementManageDTO.getExhibitorId() != null && StrUtil.isNotBlank(arrangementManageDTO.getSiteType()) && arrangementManageDTO.getSupervisedId() != null) {
            if (ExhibitorSiteTypeEnum.STANDARD.eq(arrangementManageDTO.getSiteType())) {
                ServiceProvider builder = serviceProviderService.getById(arrangementManageDTO.getSupervisedId());
                if (builder != null) {
                    // 标摊展位传搭建商系统负责人和手机号
                    arrangementManageDTO.setConstructionPrincipal(builder.getPrincipalName());
                    arrangementManageDTO.setPrincipalPhone(builder.getPrincipalMobile());
                }
            }
            if (ExhibitorSiteTypeEnum.SPECIAL.eq(arrangementManageDTO.getSiteType())) {
                ReportBuilderVO reportBuilderVO = venueManageReportBuilderService.getByExhibitorId(arrangementManageDTO.getExhibitorId());
                if (reportBuilderVO != null) {
                    // 封装搭建商施工负责人和电话
                    arrangementManageDTO.setConstructionPrincipal(reportBuilderVO.getConstructionPrincipal());
                    arrangementManageDTO.setPrincipalPhone(reportBuilderVO.getPrincipalPhone());
                }
            }
        }
        // 保存布撤展管理记录
        ArrangementManage arrangementManage = BeanUtil.toBean(arrangementManageDTO, ArrangementManage.class);
        this.save(arrangementManage);
        // 添加布撤展管理上传的附件
        List<AttachmentFileDTO> attachmentFileDTOList = arrangementManageDTO.getAttachmentFileDTOs();
        if (attachmentFileDTOList != null && !attachmentFileDTOList.isEmpty()) {
            attachmentFileDTOList.forEach((s) -> {
                s.setBusinessId(arrangementManage.getId());
                s.setBusinessType(ARRANGE_MANAGE_BUSINESS_TYPE);
            });
            venueManageAttachFileService.saveOrUpdateAttachmentFile(attachmentFileDTOList);
        }
        return arrangementManage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveForHomeCheckCertificate(ArrangementManageDTO arrangementManageDTO) {
        log.info("saveForHomeCheckBuilderCertificate - 主场巡检保存搭建商证件的管理记录, arrangementManageDTO={}", arrangementManageDTO);
        saveForCheckBuilderCertificate(arrangementManageDTO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ArrangementManage saveFoVenueCheckCertificate(ArrangementManageDTO arrangementManageDTO) {
        log.info("saveFoVenueCheckBuilderCertificate - 场馆巡检保存主场搭建商证件的管理记录, arrangementManageDTO={}", arrangementManageDTO);
        if (ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.eq(arrangementManageDTO.getSupervisedType())) {
            return saveForCheckHomeCertificate(arrangementManageDTO);
        }
        if (ServiceProviderTypeEnum.BUILD_SERVICE_PROVIDER.eq(arrangementManageDTO.getSupervisedType())) {
            return saveForCheckBuilderCertificate(arrangementManageDTO);
        }
        return null;
    }

    private ArrangementManage saveForCheckHomeCertificate(ArrangementManageDTO arrangementManageDTO) {
        String spaceCode = arrangementManageDTO.getSpaceCode();
        if (StrUtil.isBlank(spaceCode)) {
            log.error("展厅编码为空");
            return saveArrangementManage(arrangementManageDTO);
        }
        // 查询服务商在展会中负责的展厅
        List<ServiceProviderSpaceVO> serviceProviderSpaceList = serviceProviderSpaceService.queryByExhibitionId(arrangementManageDTO.getExhibitionManageId(), arrangementManageDTO.getSupervisedId());
        if (serviceProviderSpaceList == null || serviceProviderSpaceList.isEmpty()) {
            log.error("违规企业不存在负责的展厅, exhibitionManageId={}, supervisedId={}", arrangementManageDTO.getExhibitionManageId(), arrangementManageDTO.getSupervisedId());
            return saveArrangementManage(arrangementManageDTO);
        }
        // 补全展厅名称
        serviceProviderSpaceList.forEach(serviceProviderSpaceVO -> {
            if (spaceCode.equals(serviceProviderSpaceVO.getSpaceCode())) {
                arrangementManageDTO.setSpaceName(serviceProviderSpaceVO.getSpaceName());
            }
        });
        return saveArrangementManage(arrangementManageDTO);
    }

    private ArrangementManage saveForCheckBuilderCertificate(ArrangementManageDTO arrangementManageDTO) {
        if (StrUtil.isBlank(arrangementManageDTO.getSpaceCode()) || StrUtil.isBlank(arrangementManageDTO.getSiteCode())) {
            return saveArrangementManage(arrangementManageDTO);
        }
        // 通过展会ID，搭建商ID，展厅号，展位号 查询展商展位信息
        ExhibitorDTO exhibitorDTO = new ExhibitorDTO();
        exhibitorDTO.setExhibitionManageId(arrangementManageDTO.getExhibitionManageId());
        exhibitorDTO.setBuilderId(arrangementManageDTO.getSupervisedId());
        exhibitorDTO.setSpaceCode(arrangementManageDTO.getSpaceCode());
        exhibitorDTO.setSiteCode(arrangementManageDTO.getSiteCode());
        List<ExhibitorVO> exhibitorList = venueManageExhibitorService.queryExhibitors(exhibitorDTO);
        if (exhibitorList == null || exhibitorList.isEmpty()) {
            return saveArrangementManage(arrangementManageDTO);
        }
        ExhibitorVO exhibitorVO = exhibitorList.get(0);
        arrangementManageDTO.setExhibitorId(exhibitorVO.getId());
        arrangementManageDTO.setExhibitorName(exhibitorVO.getExhibitorName());
        arrangementManageDTO.setSpaceCode(exhibitorVO.getSpaceCode());
        arrangementManageDTO.setSpaceName(exhibitorVO.getSpaceName());
        arrangementManageDTO.setSiteCode(exhibitorVO.getSiteCode());
        arrangementManageDTO.setSiteName(exhibitorVO.getSiteName());
        arrangementManageDTO.setSiteType(exhibitorVO.getSiteType().getCode());
        arrangementManageDTO.setSiteArea(exhibitorVO.getSiteArea());
        arrangementManageDTO.setSupervisedName(exhibitorVO.getBuilderName());
        arrangementManageDTO.setSupervisedType(ServiceProviderTypeEnum.BUILD_SERVICE_PROVIDER.getCode());
        return saveArrangementManage(arrangementManageDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateArrangementManage(ArrangementManageDTO arrangementManageDTO) {
        log.info("updateArrangementManage - 修改布撤展管理信息, arrangementManageDTO={}", arrangementManageDTO);
        // 更新布撤展管理记录
        ArrangementManage arrangementManage = BeanUtil.toBean(arrangementManageDTO, ArrangementManage.class);
        this.updateById(arrangementManage);
        // 更新附件
        List<AttachmentFileDTO> attachmentFileDTOList = arrangementManageDTO.getAttachmentFileDTOs();
        if (attachmentFileDTOList == null || attachmentFileDTOList.isEmpty()) {
            return true;
        }
        // 删除布撤展管理的旧附件
        venueManageAttachFileService.deleteBatchByBusinessId(arrangementManageDTO.getId());
        // 保存布撤展管理的新附件
        attachmentFileDTOList.forEach((s) -> {
            s.setBusinessId(arrangementManage.getId());
            s.setBusinessType(ARRANGE_MANAGE_BUSINESS_TYPE);
            venueManageAttachFileService.saveOrUpdateAttachmentFile(attachmentFileDTOList);
        });
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateHasPunish(Long id) {
        log.info("updateHasPunish - 更新处罚状态为已处罚, arrangementManageDTO={}", id);
        ArrangementManage arrangementManage = getById(id);
        if (arrangementManage == null) {
            throw BizException.wrap(VenueServiceExceptionCode.VIOLATION_RECORD_NOT_EXIST);
        }
        arrangementManage.setPunishStatus(ArrangementManagePunishStatusEnum.HAS_PUNISH);
        return updateById(arrangementManage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateNotPunish(Long id) {
        log.info("updateNotPunish - 更新处罚状态为未处罚, id={}", id);
        ArrangementManage arrangementManage = getById(id);
        if (arrangementManage == null) {
            throw BizException.wrap(VenueServiceExceptionCode.VIOLATION_RECORD_NOT_EXIST);
        }
        List<ViolationRecord> violationRecordList = violationRecordService.listHomeCheckViolationRecordByArrangementId(id);
        if (violationRecordList != null && !violationRecordList.isEmpty()) {
            return false;
        }
        arrangementManage.setPunishStatus(ArrangementManagePunishStatusEnum.NOT_PUNISH);
        return updateById(arrangementManage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delArrangementManage(Long id) {
        // 删除布撤展管理记录
        ArrangementManage arrangementManage = new ArrangementManage();
        arrangementManage.setId(id);
        arrangementManage.setIsDeleted(BusinessConstant.DELETE_YES);
        this.updateById(arrangementManage);
        // 删除附件
        venueManageAttachFileService.deleteBatchByBusinessId(id);
        return true;
    }

    private QueryWrapper<ArrangementManage> createArrangementManageQueryWrapper(ArrangementManageDTO model) {
        QueryWrapper<ArrangementManage> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(ArrangementManage::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Objects.nonNull(model.getExhibitionManageId()), ArrangementManage::getExhibitionManageId, model.getExhibitionManageId())
                .like(StrUtil.isNotBlank(model.getSupervisedName()), ArrangementManage::getSupervisedName, model.getSupervisedName())
                .like(StrUtil.isNotBlank(model.getExhibitorName()), ArrangementManage::getExhibitorName, model.getExhibitorName())
                .eq(StrUtil.isNotBlank(model.getSpaceCode()), ArrangementManage::getSpaceCode, model.getSpaceCode())
                .like(StrUtil.isNotBlank(model.getSiteName()), ArrangementManage::getSiteName, model.getSiteName())
                .eq(StrUtil.isNotBlank(model.getSiteType()), ArrangementManage::getSiteType, model.getSiteType())
                .in(model.getArrangementSourceList() != null && !model.getArrangementSourceList().isEmpty(), ArrangementManage::getArrangementSource, model.getArrangementSourceList())
                .and(StrUtil.isNotBlank(model.getSearchContent()), searchContentQueryWrapper ->
                        searchContentQueryWrapper
                                .like(ArrangementManage::getSiteName, model.getSearchContent())
                                .or()
                                .like(ArrangementManage::getSupervisedName, model.getSearchContent())
                                .or()
                                .like(ArrangementManage::getConstructionPrincipal, model.getSearchContent())
                                .or()
                                .like(ArrangementManage::getPrincipalPhone, model.getSearchContent())
                )
                .and(model.getIsHomeQuery() == null || !model.getIsHomeQuery(),
                        isNotHomeQueryQueryWrapper -> isNotHomeQueryQueryWrapper.eq(Objects.nonNull(model.getSupervisorId()), ArrangementManage::getSupervisorId, model.getSupervisorId())
                )
                // 如果是主场查询，则查询主场巡检的数据，或者是场馆巡检到的主场记录，或者主场负责的搭建商的记录
                .and(model.getIsHomeQuery() != null && model.getIsHomeQuery() && Objects.nonNull(model.getSupervisorId()), isHomeQueryQueryWrapper ->
                        isHomeQueryQueryWrapper
                                .eq(ArrangementManage::getSupervisorId, model.getSupervisorId())
//                                .or(venueCheckQueryWrapper ->
//                                        venueCheckQueryWrapper
//                                                .eq(ArrangementManage::getSupervisedId, model.getSupervisorId())
//                                                .eq(ArrangementManage::getArrangementSource, ArrangementManageArrangementSourceEnum.VENUE_CHECK))
                                .or(model.getSpaceCodeList() != null && !model.getSpaceCodeList().isEmpty(), venueCheckQueryWrapper ->
                                        venueCheckQueryWrapper
                                                .in(ArrangementManage::getSpaceCode, model.getSpaceCodeList())
                                                .eq(ArrangementManage::getSupervisedType, ServiceProviderTypeEnum.BUILD_SERVICE_PROVIDER.getCode())
                                                .eq(ArrangementManage::getArrangementSource, ArrangementManageArrangementSourceEnum.VENUE_CHECK))
                )
        ;
        return queryWrapper;
    }
}
